function AppLoader() {


    /**
    * Array of all necessary JavaScript files that need to be loaded before
    * mess application can function properly.
    *
    * @private
    * @property  files
    * @type      {Array}
    */
    this.files = new Array();

    /**
    * Index of file beeing currently processed
    *
    * @private
    * @property  fileIndex
    * @type      {Number}
    * @Cyan   -1
    */
    this.fileIndex = -1;

    /**
    * Loader box dom object
    *
    * @private
    * @property  domObject
    * @type      {DOM}
    * @Cyan   null
    */
    this.domObject = null;

    /**
    * Local XHR object
    *
    * @private
    * @property  xhr
    * @type      {XMLHTTP}
    */
    this.xhr = new GenericAjax();

    this.APPLICATION_ENTRY_POINT = "/mess/LoadStartPage.action";

    // perform initialization
    this.build();
};

    /**
    * Perform all necessary initialization routines
    *
    * @public
    * @method  init
    */
    AppLoader.prototype.build = function() {

        // save object instance for later usage
        AppLoader.prototype.object = this;
        
        // init files array
        this.initFilesArray();

        // build loading box dom object
        this.buildDOMObject();
    };

    /**
    * Build application loader dom presentation object
    *
    * @private
    * @method   buildDOMObject
    */
    AppLoader.prototype.buildDOMObject = function() {

        var container = document.createElement("div");
            container.id = "appLoaderBox";
            container.className = "AppLoaderBox";
            container.onmousedown = function() { return false; };
            container.onclick = function() { return true; };

            var separator1 = document.createElement("div");
                separator1.className = "appLoaderBoxSeparator1";

            this.headerDom = document.createElement("div");
            this.headerDom.id = "appLoaderBoxHeader";
            this.headerDom.className = "AppLoaderBoxHeader";
            this.headerDom.appendChild( document.createTextNode("Loading..."));

            this.contentDom = document.createElement("div");
            this.contentDom.id = "appLoaderBoxContent";
            this.contentDom.className = "AppLoaderBoxContent";

            var separator2 = document.createElement("div");
                separator2.className = "appLoaderBoxSeparator2";

        container.appendChild(this.headerDom);
        container.appendChild(separator1);
        container.appendChild(this.contentDom);
        container.appendChild(separator2);

        this.domObject = container;
        
        // position box
        this.domObject.style.left = ((document.body.clientWidth/2) - 200)+'px';
        this.domObject.style.top = ((document.body.clientHeight/2) - 45)+'px';
    };

    /**
    * Initialize array of remote javascript file names
    *
    * @private
    * @method  initFilesArray
    */
    AppLoader.prototype.initFilesArray = function() {

//        this.files.push( new FileEntry('js/mess/core/common/collections/Iterator.js' ,null));
//        this.files.push( new FileEntry('js/mess/core/common/collections/List.js', null));
//        this.files.push( new FileEntry('js/mess/core/common/collections/Map.js', null));
//        this.files.push( new FileEntry('js/mess/core/common/BasicElements.js', null));
//        this.files.push( new FileEntry('js/mess/core/common/GenericAjax.js', null));
//        this.files.push( new FileEntry('js/mess/core/common/Util.js', null));
//        this.files.push( new FileEntry('js/mess/ui/common/MessEventUtil.js', null));
//        this.files.push( new FileEntry('js/mess/ui/common/MessUIElement.js', null));
//        this.files.push( new FileEntry('js/mess/ui/common/MessCoordinate.js', null));
//        this.files.push( new FileEntry('js/mess/ui/controls/common/buttons/ActionButton.js', null));
//        this.files.push( new FileEntry('js/mess/ui/controls/treeview/MSTreeViewControl.js', null));
//        this.files.push( new FileEntry('js/mess/ui/controls/treeview/MSTreeViewElement.js', null));
//        this.files.push( new FileEntry('js/mess/ui/controls/tabview/MSTabControl.js', null));
//        this.files.push( new FileEntry('js/mess/ui/controls/tabview/MSTab.js', null));
//        this.files.push( new FileEntry('js/mess/ui/controls/tabview/buttons/CloseTabButton.js', null));
//        this.files.push( new FileEntry('js/mess/ui/controls/tabview/buttons/NextTabButton.js', null));
//        this.files.push( new FileEntry('js/mess/ui/controls/tabview/buttons/PrevTabButton.js', null));
//        this.files.push( new FileEntry('js/mess/ui/controls/windows/buttons/ShrinkButton.js', null));
//        this.files.push( new FileEntry('js/mess/ui/controls/windows/buttons/CloseButton.js', null));
//        this.files.push( new FileEntry('js/mess/ui/controls/windows/buttons/ResizeButton.js', null));
//        this.files.push( new FileEntry('js/mess/ui/controls/windows/buttons/MaximizeButton.js', null));
//        this.files.push( new FileEntry('js/mess/ui/controls/windows/Window.js', null));
//        this.files.push( new FileEntry('js/mess/ui/controls/windows/ResizingFrame.js', null));
//        this.files.push( new FileEntry('js/mess/ui/controls/windows/MovingFrame.js', null));
//        this.files.push( new FileEntry('js/mess/ui/controls/windows/WindowControl.js', null));
//        this.files.push( new FileEntry('js/mess/ui/layout/MovingSplitter.js', null));
//        this.files.push( new FileEntry('js/mess/ui/layout/Panel.js', null));
//        this.files.push( new FileEntry('js/mess/ui/layout/Splitter.js', null));
//        this.files.push( new FileEntry('js/mess/core/application/builder/XmlDataParser.js', null));
//        this.files.push( new FileEntry('js/mess/core/application/Environment.js', null));
        this.files.push( new FileEntry('./js/mess/core/application/GarbageCollector.js', null));
    };

    /**
    * Starts mess application loading process
    *
    * @public
    * @method  startLoading
    */
    AppLoader.prototype.startLoading = function() {

        // display loading box
        document.body.appendChild(this.domObject);


        setTimeout(this.__getRemoteFile, 300);
    };

    /**
    * Finishes mess application loading process
    *
    * @private
    * @method   finishLoading
    */
    AppLoader.prototype.finishLoading = function() {


        // go to application entry point
        this.xhr = new GenericAjax();
        this.xhr.send(this.APPLICATION_ENTRY_POINT, this.finishLoadingCallback);
    };

    /**
    * Callback method for finishLoading - gets xml from server and starts view building
    * process
    *
    * @callback
    * @method  finishLoadingCallback
    */
    AppLoader.prototype.finishLoadingCallback = function() {

        var loader = AppLoader.prototype.object;

        if (loader.xhr.isReady()) {

            var xmlContent = loader.xhr.getResponseXML();
            if (xmlContent !== null) {
            // got valid xml, start application

                env = new Environment();   // implicit global variable env
                env.startApplication(xmlContent);
            }
        }
    };


    /**
    * Gets single remote file from server
    *
    * @private
    * @method    getRemoteFile
    */
    AppLoader.prototype.getRemoteFile = function() {

        this.fileIndex++;
        this.xhr.send(this.files[this.fileIndex].getFileURI(), this.getRemoteFileCallback);
    };

    AppLoader.prototype.__getRemoteFile = function() {

        var loader = AppLoader.prototype.object;
        loader.getRemoteFile();
    }

    /**
    * Callback method for getRemoteFile - finishes remote request
    *
    * @callback
    * @method    getRemoteFileCallback
    */
    AppLoader.prototype.getRemoteFileCallback = function() {

        var loader = AppLoader.prototype.object;

        if (loader.xhr.isReady()) {
            // load script to global scope
            var content = loader.xhr.getResponseText();
            if (window.execScript) {
                window.execScript(content);
            }
            else {
                window.eval(content);
            }

            // show loaded file name
            loader.showFileEntry();

            if (loader.fileIndex < loader.files.length-1) {
            // continue with next file
                loader.getRemoteFile();
            }
            else {
            // finished loading files
                loader.finishLoading();
            }
        }
    };




    /**
    * Prints information about file name that has been remotely loaded from server
    *
    * @private
    * @method   showFileEntry
    */
    AppLoader.prototype.showFileEntry = function() {

        var file = this.files[this.fileIndex];
        
        if (this.contentDom.childNodes.length > 3) {
            this.contentDom.removeChild(this.contentDom.firstChild);
        }

        var oDiv = document.createElement("div");
            oDiv.appendChild( document.createTextNode(file.getFileURI()) );


        this.contentDom.appendChild(oDiv);
    }













